package com.ziiwee.reduce.describe;

import com.ziiwee.reduce.describe.register.*;
import com.ziiwee.reduce.describe.types.DefaultTypeProviderContext;
import com.ziiwee.reduce.describe.types.DefaultTypeProviderRegister;
import com.ziiwee.reduce.describe.types.TypeProviderContext;
import com.ziiwee.reduce.describe.types.TypeProviderRegister;
import com.ziiwee.reduce.describe.types.impls.ArrayTypeProvider;
import com.ziiwee.reduce.describe.types.impls.PageTypeProvider;
import com.ziiwee.reduce.describe.types.impls.PageableTypeProvider;
import com.ziiwee.reduce.rest.auto.ResourceMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.ServerResponse;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.List;

/**
 * @author ziiwee
 * @date 2020/8/13
 */
@Configuration
@Import(DescribeEndpoint.class)
public class DescribeAutoConfiguration {

//    @Bean
//    public RouterFunction<ServerResponse> describeRouterFunction(DescribeHolder describeHolder){
//
//    }

    @Bean
    public DescribeHolder describeHolder(TypeProviderContext typeProviderContext, List<DescribeRegister> registers) {
        return new DefaultDescribeHolder(registers, typeProviderContext);
    }

    @Bean
    @ConditionalOnMissingBean(RequestMappingDescribeRegister.class)
    public RequestMappingDescribeRegister requestMappingDescribeRegister(ApplicationContext applicationContext) {
        DefaultRequestMappingDescribeRegister register = new DefaultRequestMappingDescribeRegister(applicationContext, Integer.MAX_VALUE);
        register.register(applicationContext.getBean(RequestMappingHandlerMapping.class));
        return register;
    }

    @Bean
    @ConditionalOnMissingBean
    @Autowired(required = false)
    public ResourceInfoDescribeRegister resourceInfoDescribeRegister(ResourceMapping resourceMapping) {
        DefaultResourceInfoDescribeRegister register = new DefaultResourceInfoDescribeRegister(Integer.MIN_VALUE);
        if (resourceMapping != null) {
            resourceMapping.getAll().forEach(register::register);
        }
        return register;
    }

    @Bean
    public TypeProviderRegister typeProviderRegister() {
        DefaultTypeProviderRegister register = new DefaultTypeProviderRegister();
        register.registerProvider(new PageTypeProvider());
        register.registerProvider(new ArrayTypeProvider());
        register.registerProvider(new PageableTypeProvider());
        return register;
    }

    @Bean
    public TypeProviderContext typeProviderContext(TypeProviderRegister typeProviderRegister) {
        return new DefaultTypeProviderContext(typeProviderRegister);
    }

}
